package com.yunmasoft.service.pay.alipay;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeCloseModel;
import com.alipay.api.domain.AlipayTradeRefundModel;
import com.alipay.api.internal.util.json.JSONWriter;
import com.alipay.api.request.AlipayTradeCloseRequest;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.request.AlipayTradeWapPayRequest;
import com.alipay.api.response.AlipayTradeCloseResponse;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.common.bean.ClientOsInfo;
import com.common.dict.Constant2;
import com.common.util.BeanHWUtil;
import com.common.util.RedisCacheUtil;
import com.common.util.SystemHWUtil;
import com.common.util.WebServletUtil;
import com.house.ujiayigou.thirdpart.alipay.config.AlipayConfig;
import com.house.ujiayigou.thirdpart.alipay.info.AlipayTradePcPayModel;
import com.house.ujiayigou.thirdpart.alipay.util.AlipayNotify;
import com.house.ujiayigou.thirdpart.alipay.util.AlipaySubmit;
import com.io.hw.json.HWJacksonUtils;
import com.io.hw.json.JSONHWUtil;
import com.string.widget.util.ValueWidget;
import com.time.util.TimeHWUtil;
import oa.util.SpringMVCUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.Map;

/**
 * Created by David on 15/8/30.
 */
@Service("alipay")
public class AliPayService extends PayService implements PayOperation {

    public static final String ALI_PAY_CHANNELS = "balance,moneyFund,coupon,pcredit,creditCard,credit_group,promotion";
    public static final String QR_PAY_MODE_SIMPLE = "0";
    protected final static Logger logger = LoggerFactory.getLogger("pay");
    private String qr_pay_mode;

    public AliPayService() {
    }

    public static String buildExtraCommonParam(String random_id, String userIdAndLoginnameAndOrgId) {
        return "alipay::" + random_id + "::" + userIdAndLoginnameAndOrgId;
    }

    /***
     * 关闭订单,关闭交易(正常)
     * @param orderNo
     * @param userId
     * @return
     */
    public static AlipayTradeCloseResponse closeOrder(String orderNo, String userId) {
// SDK 公共请求类，包含公共请求参数，以及封装了签名与验签，开发者无需关注签名与验签
        //调用RSA签名方式
        AlipayClient client = getAlipayClient();
        AlipayTradeCloseRequest request = new AlipayTradeCloseRequest();
        AlipayTradeCloseModel model = new AlipayTradeCloseModel();
        model.setOperatorId(userId);
        model.setOutTradeNo(orderNo);

        if (ValueWidget.isNullOrEmpty(request.getBizContent())) {
            JSONWriter writer = new JSONWriter();
            String body = writer.write(model, true);
            request.setBizContent(body);//ValueWidget.escapeHTML(HWJacksonUtils.getJsonP4Alipay(model))

        }

        request.setNotifyUrl("http://house.yhskyc.com/info/request_a");

        try {
            AlipayTradeCloseResponse alipayResponse = (AlipayTradeCloseResponse) client.execute(request);
//            System.out.println("close :" + alipayResponse.getBody());
            return alipayResponse;
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        return null;
    }

    /***
     * 退款
     * @param orderNo
     * @param userId
     * @return
     */
    public static AlipayTradeRefundResponse refundOrder(String orderNo, String userId, String refundAmount, String refundReason) {
// SDK 公共请求类，包含公共请求参数，以及封装了签名与验签，开发者无需关注签名与验签
        //调用RSA签名方式
        AlipayClient client = getAlipayClient();
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
        AlipayTradeRefundModel model = new AlipayTradeRefundModel();
        model.setOperatorId(userId);
        model.setOutTradeNo(orderNo);
        model.setRefundAmount(refundAmount);
        model.setRefundReason(refundReason);
        if (ValueWidget.isNullOrEmpty(request.getBizContent())) {
            JSONWriter writer = new JSONWriter();
            String body = writer.write(model, true);
            request.setBizContent(body);//ValueWidget.escapeHTML(HWJacksonUtils.getJsonP4Alipay(model))

        }

        request.setNotifyUrl("http://house.yhskyc.com/info/request_a");

        try {
            AlipayTradeRefundResponse alipayResponse = (AlipayTradeRefundResponse) client.execute(request);
            System.out.println("close :" + alipayResponse.getBody());
            return alipayResponse;
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        return null;
    }

    private static String buildPayPageForm(com.house.ujiayigou.thirdpart.alipay.info.PayFormInfo payFormInfo) {
// SDK 公共请求类，包含公共请求参数，以及封装了签名与验签，开发者无需关注签名与验签
        //调用RSA签名方式
        AlipayClient client = getAlipayClient();
        AlipayTradePagePayRequest alipay_request = getAlipayTradePagePayRequest(payFormInfo);

        // form表单生产
        String form = "";
        try {
            // 调用SDK生成表单
            form = client.pageExecute(alipay_request).getBody()/*.replace(".submit()", "")*/;
            System.out.println("form :" + form);
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        return form;
    }

    private static AlipayTradePagePayRequest getAlipayTradePagePayRequest(com.house.ujiayigou.thirdpart.alipay.info.PayFormInfo payFormInfo) {
        AlipayTradePagePayRequest alipay_request = new AlipayTradePagePayRequest();

        // 封装请求支付信息
        AlipayTradePcPayModel model = new AlipayTradePcPayModel();
        model.setOutTradeNo(payFormInfo.getOut_trade_no());
        model.setSubject(payFormInfo.getSubject());
        model.setTotalAmount(payFormInfo.getTotal_amount());
        model.setBody(payFormInfo.getBody());
        model.setTimeoutExpress(payFormInfo.getTimeout_express());
        model.setProductCode(payFormInfo.getProduct_code());
        model.setPassbackParams(payFormInfo.getExtra_common_param());
        if (!ValueWidget.isNullOrEmpty(payFormInfo.getQr_pay_mode())) {
            model.setQrPayMode(payFormInfo.getQr_pay_mode());
        }
        if (!ValueWidget.isNullOrEmpty(payFormInfo.getSeller_id())) {
            model.setSellerId(payFormInfo.getSeller_id());
        }
        //enable_pay_channels 可用渠道，用户只能在指定渠道范围内支付当有多个渠道时用“,”分隔
        model.setEnablePayChannels(ALI_PAY_CHANNELS);
//        alipay_request.setBizModel(model);
        if (ValueWidget.isNullOrEmpty(alipay_request.getBizContent())) {
            JSONWriter writer = new JSONWriter();
            String body = writer.write(model, true);
            alipay_request.setBizContent(body);//ValueWidget.escapeHTML(HWJacksonUtils.getJsonP4Alipay(model))

        }

        // 设置异步通知地址 TODO
        String notifyUrl = RedisCacheUtil.getAliNotifyUrl(ValueWidget.getBsvcOrderNo(payFormInfo.getOut_trade_no())  /*.split("__")[0]*/);
        if (ValueWidget.isNullOrEmpty(notifyUrl)) {
            notifyUrl = AlipayConfig.base_url + (AlipayConfig.notify_url.startsWith(Constant2.SLASH) ? AlipayConfig.notify_url : Constant2.SLASH + AlipayConfig.notify_url);
        }
        alipay_request.setNotifyUrl(notifyUrl /*"http://house.yhskyc.com/info/request_a"*/);
        alipay_request.setReturnUrl(AlipayConfig.base_url + AlipayConfig.wap_return_url);
        // 设置同步地址
//        alipay_request.setReturnUrl(Const.return_url);

        //打印日志
        logger.error("notify url:" + alipay_request.getNotifyUrl());
        System.out.println("notify url :" + alipay_request.getNotifyUrl());
        logger.error("return url:" + alipay_request.getReturnUrl());
        System.out.println("return url :" + alipay_request.getReturnUrl());
        String bizContentJson = JSONHWUtil.formatJson(alipay_request.getBizContent());
        logger.error("bizContent :" + SystemHWUtil.CRLF + bizContentJson);
        System.out.println("bizContent :" + bizContentJson);
        return alipay_request;
    }

   /* public static AlipayTradeCancelResponse cancelAliOrder(String orderNo, String userId) {
// SDK 公共请求类，包含公共请求参数，以及封装了签名与验签，开发者无需关注签名与验签
        //调用RSA签名方式
        AlipayClient client = getAlipayClient();
        AlipayTradeCancelRequest request = new AlipayTradeCancelRequest();
        AlipayTradeCloseModel model = new AlipayTradeCloseModel();
        model.setOperatorId(userId);
        model.setOutTradeNo(orderNo);

        if (ValueWidget.isNullOrEmpty(request.getBizContent())) {
            JSONWriter writer = new JSONWriter();
            String body = writer.write(model, true);
            request.setBizContent(body);//ValueWidget.escapeHTML(HWJacksonUtils.getJsonP4Alipay(model))

        }

        request.setNotifyUrl("http://house.yhskyc.com/info/request_a");

        try {
            AlipayTradeCancelResponse alipayResponse = (AlipayTradeCancelResponse) client.execute(request);
            System.out.println("close :" + alipayResponse.getBody());
            return alipayResponse;
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        return null;
    }*/

    /***
     * 支付宝手机端
     * @param payFormInfo
     * @return
     */
    private static String buildWapPayPageForm(com.house.ujiayigou.thirdpart.alipay.info.PayFormInfo payFormInfo) {
// SDK 公共请求类，包含公共请求参数，以及封装了签名与验签，开发者无需关注签名与验签
        payFormInfo.setQr_pay_mode(null);
//        payFormInfo.setSeller_id(AlipayConfig.seller_id);
        //调用RSA签名方式
        AlipayClient client = getAlipayClient();
        AlipayTradeWapPayRequest alipay_request = new AlipayTradeWapPayRequest();

        AlipayTradePagePayRequest alipayPCrequest = getAlipayTradePagePayRequest(payFormInfo);
        BeanHWUtil.copyProperties(alipayPCrequest, alipay_request, "ApiMethodName");

        // form表单生产
        String form = "";
        try {
            // 调用SDK生成表单
            form = client.pageExecute(alipay_request).getBody();
            System.out.println("form :" + form);
        } catch (AlipayApiException e) {
            e.printStackTrace();
        }
        return form;
    }

    private static AlipayClient getAlipayClient() {
        return new DefaultAlipayClient(AlipayConfig.URL, AlipayConfig.APPID, AlipayConfig.RSA2_PRIVATE_KEY, AlipayConfig.FORMAT, AlipayConfig.input_charset, AlipayConfig.ALIPAY_PUBLIC_KEY, AlipayConfig.sign_type);
    }

    public String verify(Map<String, String> params) {

        if (AlipayNotify.verify(params)) {
            return "success";
        } else {
            return "fail";
        }
    }

    public String preparePostRequest(com.house.ujiayigou.thirdpart.alipay.info.PayFormInfo payFormInfo
    ) {
//            com.house.ujiayigou.com.house.ujiayigou.thirdpart.alipay.info.PayFormInfo payFormInfo = new com.house.ujiayigou.com.house.ujiayigou.thirdpart.alipay.info.PayFormInfo();
//            payFormInfo.setOut_trade_no(out_trade_no);
//            payFormInfo.setSubject(subject);
//            payFormInfo.setBody(body);
//            payFormInfo.setTotal_amount(total_fee);
        payFormInfo.setTimeout_express(AlipayConfig.TIMEOUT_EXPRESS);
        Object param = getCustomConfigParam();
        if (null != param) {
            payFormInfo.setQr_pay_mode(QR_PAY_MODE_SIMPLE);
        }
        ClientOsInfo info = WebServletUtil.getMobileOsInfo(SpringMVCUtil.getRequest());
        if (info.isMobile()) {
            return buildWapPayPageForm(payFormInfo);
        } else {
            return buildPayPageForm(payFormInfo);
        }


    }

    public String compareOrderPayPrice(String orderNo, String strShouldPay, String userId) {
        String orderNoWithSuffix = RedisCacheUtil.getOrderNoSuffix(orderNo);
        //判断是否修改了金额
        if (RedisCacheUtil.hasChangedPayPrice(orderNo, strShouldPay)) {
            logger.error("修改了订单金额:" + strShouldPay);
//            AlipayTradeCancelResponse alipayTradeCancelResponse = aliPayService.cancelAliOrder(orderNo, getCurrentUserId());
            AlipayTradeCloseResponse alipayTradeCloseResponse = closeOrder(orderNoWithSuffix, userId);
            if (!alipayTradeCloseResponse.getCode().equals("10000")) {//注意!!!!交易不存在并一定是没有生成支付宝订单,可能因为还没有扫描二维码
                logger.error(HWJacksonUtils.getJsonP(alipayTradeCloseResponse));
            }
            orderNoWithSuffix = RedisCacheUtil.getOrderNoSuffix(orderNo, true);
        }
        RedisCacheUtil.saveAliPayPrice(orderNo, strShouldPay);
        return orderNoWithSuffix;
    }

    public Map<String, String> cancelOrderParam(String orderNo, String userId) {
        Map<String, String> sParaTemp = new HashMap<String, String>();
        sParaTemp.put("app_id", AlipayConfig.APPID);
        sParaTemp.put("method", "alipay.trade.close");
        sParaTemp.put("format", "JSON");
        sParaTemp.put("charset", AlipayConfig.input_charset);
//        sParaTemp.put("sign_type","RSA");
        sParaTemp.put("timestamp", TimeHWUtil.getCurrentDateTime());
        sParaTemp.put("version", "1.0");
        sParaTemp.put("notify_url", "http://blog.yhskyc.com/convention2/info/request_a");//vapp_auth_token 非必填


        Map<String, String> bizParaTemp = new HashMap<String, String>();

        bizParaTemp.put("out_trade_no", orderNo);//out_trade_no 和trade_no 二选一就行
        bizParaTemp.put("operator_id", userId);

        sParaTemp.put("biz_content", HWJacksonUtils.getJsonP(bizParaTemp));
//        sParaTemp.put("app_id",AlipayConfig.partner);
//        sParaTemp.put("app_id",AlipayConfig.partner);
        return sParaTemp;
    }

   /* public void cancelOrderTmp(String orderNo, String userId) {
        Map<String, String> sParaTemp = cancelOrderParam(orderNo, userId);
        //待请求参数数组
        Map<String, String> sPara = AlipaySubmit.buildRequestPara(sParaTemp, "RSA2");
        String response = HttpUtils.get("https://openapi.alipay.com/gateway.do", sPara, null);
        System.out.println(" :" + response);
    }*/

    /***
     * 获取定制化参数<br />
     * 正常情况下,不需要重写
     * @return
     */
    public Object getCustomConfigParam() {
        return qr_pay_mode;
    }

    public void setCustomConfigParam(Object qr_pay_mode) {
        this.qr_pay_mode = (String) qr_pay_mode;
    }

    public String preparePostRequest2(String out_trade_no,
                                      String subject,
                                      String total_fee,
                                      String body,
                                      String show_url,
                                      String receive_name,
                                      String receive_address,
                                      String receive_zip,
                                      String receive_phone,
                                      String receive_mobile,
                                      String seller_account,
                                      String random_id,
                                      String productName,
                                      String userIdAndLoginnameAndOrgId/*以下划线分隔并且不能有空格,例如"61000257911_13719486139_90001018119" **/
    ) {
        String payment_type = "1";
        //必填，不能修改
        //服务器异步通知页面路径
        String notify_url = null;//Const.notify_url;//"http://"+Const.notify_url;
//    String notify_url ="http://blog.yhskyc.com/convention2/info/request_a";
        //需http://格式的完整路径，不能加?id=123这类自定义参数
        System.out.println("aduN +:   " + notify_url);
        //页面跳转同步通知页面路径
        //String return_url = "http://"+Const.return_url;

        String return_url = null;//Const.base_url +  AlipayConfig.wap_return_url;//"http://" + Const.base_url +  AlipayConfig.wap_return_url;
        System.out.println("adu +:   " + return_url);
        //防钓鱼时间戳
        String anti_phishing_key = "";
        //若要使用请调用类文件submit中的query_timestamp函数

        //客户端的IP地址
        String exter_invoke_ip = "";
        //非局域网的外网IP地址，如：221.0.0.1


        //////////////////////////////////////////////////////////////////////////////////
        String fee = "0.01";
    /*if(BaseController.isPayDebug()){
        fee="0.01";
    }else{*/
        fee = total_fee;
//    }
        //把请求参数打包成数组
        Map<String, String> sParaTemp = new HashMap<String, String>();
        sParaTemp.put("service", AlipayConfig.wap_service);
        sParaTemp.put("partner", AlipayConfig.partner);
        sParaTemp.put("seller_id", AlipayConfig.seller_id);
        sParaTemp.put("_input_charset", AlipayConfig.input_charset);
        sParaTemp.put("payment_type", AlipayConfig.payment_type);
        sParaTemp.put("notify_url", notify_url);
        sParaTemp.put("return_url", return_url);
        sParaTemp.put("out_trade_no", out_trade_no);
        sParaTemp.put("subject", subject);
        sParaTemp.put("total_fee", fee);
//		sParaTemp.put("body", productName);
        sParaTemp.put("body", random_id);//bsvc的唯一码
//    System.out.println("body:"+random_id);
        sParaTemp.put("app_pay", "Y");
        sParaTemp.put("show_url", show_url);//订单详情
        sParaTemp.put("anti_phishing_key", anti_phishing_key);
        sParaTemp.put("exter_invoke_ip", exter_invoke_ip);
        sParaTemp.put("it_b_pay", "24h");//m-分钟，h-小时，d-天，1c-当天（1c-当天的情况下，无论交易何时创建，都在0点关闭）
        //sParaTemp.put("extend_params", "\"{\"TRANS_MEMO\": \"促销\"}" );
//    sParaTemp.put("extra_common_param", "alipay::" + random_id + "::" + userIdAndLoginnameAndOrgId);
//		String currentCache = RedisHelper.getInstance().getKeyCache(Constant.REDIS_ID_STORE, out_trade_no) + "<br>";
//		RedisHelper.getInstance().saveKeyCacheAndExpire(Constant.REDIS_ID_STORE, out_trade_no, currentCache + ",sParaTemp:" + sParaTemp);
        assembleQrPayMode(sParaTemp);
        //建立请求
        String sHtmlText = AlipaySubmit.buildRequest(sParaTemp, "get", "确认");
        logger.error("ali:" + sHtmlText);//TODO
        return sHtmlText;
    }

    private void assembleQrPayMode(Map<String, String> sParaTemp) {
        Object param = getCustomConfigParam();
        if (null != param) {
            sParaTemp.put("qr_pay_mode", QR_PAY_MODE_SIMPLE);
        }
    }


    /**
     * 交易回调处理
     *
     * @param out_trade_no 商户订单号
     * @param trade_no     交易号
     * @param trade_status 交易状态
     * @param params
     */
    @Transactional
    public String payNotify(String out_trade_no, String trade_no, String trade_status, Map<String, String> params) {

//因为com/house/ujiayigou/web/controller/pay/PayController.java 中已经进行验签了,不用再次验签
        if (AlipayNotify.verify(params)) {//验证成功
            if (trade_status.equals("TRADE_FINISHED")) {
                // 判断该笔订单是否在商户网站中已经做过处理
                // 如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                // 如果有做过处理，不执行商户的业务程序

                // 注意：
                // 该种交易状态只在两种情况下出现
                // 1、开通了普通即时到账，买家付款成功后。
                // 2、开通了高级即时到账，从该笔交易成功时间算起，过了签约时的可退款时限（如：三个月以内可退款、一年以内可退款等）后。
            } else if (trade_status.equals("TRADE_SUCCESS")) {
                // 判断该笔订单是否在商户网站中已经做过处理
                // 如果没有做过处理，根据订单号（out_trade_no）在商户网站的订单系统中查到该笔订单的详细，并执行商户的业务程序
                // 如果有做过处理，不执行商户的业务程序

                // 注意：
                // 该种交易状态只在一种情况下出现——开通了高级即时到账，买家付款成功后。

                return PaymentNotifyhandler(out_trade_no, trade_no, params, PayService.PAYTYPE_ALIPAY, null);
            }
        }
        return "fail";
    }


    public Integer getPayType() {
        return PayService.PAYTYPE_ALIPAY;
    }
}
